from cgitb import text
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import json
import os
from datetime import datetime

class TodoListApp:
    def __init__(self, root):
        self.root = root
        self.root.title("TodoList 应用")
        self.root.geometry("800x600")
        self.root.configure(bg="#f0f8ff")
        
        # 应用图标
        try:
            self.root.iconbitmap("todo_icon.ico")
        except:
            pass
        
        # 自定义样式
        self.style = ttk.Style()
        self.style.configure("TButton", padding=6, font=("Arial", 10))
        self.style.configure("TFrame", background="#f0f8ff")
        self.style.configure("Header.TLabel", font=("Arial", 16, "bold"), background="#4b86b4", foreground="white")
        self.style.configure("Completed.TLabel", foreground="#888888", font=("Arial", 10, "overstrike"))
        
        # 任务数据
        self.tasks = []
        
        # 创建UI
        self.create_widgets()
        
        # 加载历史数据
        self.load_history_data()
        
        # 设置退出时的保存提示
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
    
    def update_status(self):
        total = len(self.tasks)
        completed = sum(1 for task in self.tasks if task["completed"])
        self.status_var.set(f"任务总数: {total} | 已完成: {completed} | 未完成: {total - completed}")

    def create_widgets(self):
        # 头部框架
        header_frame = ttk.Frame(self.root)
        header_frame.pack(fill="x", padx=20, pady=10)
        
        ttk.Label(header_frame, text="我的待办事项", style="Header.TLabel").pack(fill="x", pady=10)
        
        # 输入框架
        input_frame = ttk.Frame(self.root)
        input_frame.pack(fill="x", padx=20, pady=10)
        
        self.task_entry = ttk.Entry(input_frame, font=("Arial", 12), width=40)
        self.task_entry.pack(side="left", padx=(0, 10), fill="x", expand=True)
        self.task_entry.focus()
        self.task_entry.bind("<Return>", lambda e: self.add_task())
        
        ttk.Button(input_frame, text="添加任务", command=self.add_task).pack(side="left")
        
        # 列表框架
        list_frame = ttk.Frame(self.root)
        list_frame.pack(fill="both", expand=True, padx=20, pady=10)
        
        # 树状视图用于显示任务
        self.tree = ttk.Treeview(list_frame, columns=("text", "status", "date"), show="headings", selectmode="browse")
        self.tree.heading("#0", text="任务", anchor="w")
        self.tree.heading("text", text="内容")
        self.tree.heading("status", text="状态")
        self.tree.heading("date", text="添加日期")
        
        self.tree.column("#0", width=400, anchor="w")
        self.tree.column("text", width=300, anchor="w")
        self.tree.column("status", width=100, anchor="center")
        self.tree.column("date", width=150, anchor="center")
        
        vsb = ttk.Scrollbar(list_frame, orient="vertical", command=self.tree.yview)
        vsb.pack(side="right", fill="y")
        self.tree.configure(yscrollcommand=vsb.set)
        self.tree.pack(fill="both", expand=True)
        
        # 双击事件绑定（切换任务状态）
        self.tree.bind("<Double-1>", self.toggle_task_status)
        # 添加右键菜单
        self.tree.bind("<Button-3>", self.show_context_menu)
        # 添加缓慢双击事件
        # self.tree.bind("<Double-Button-1>", self.edit_task_content)
        
        # 按钮框架
        button_frame = ttk.Frame(self.root)
        button_frame.pack(fill="x", padx=20, pady=10)
        
        ttk.Button(button_frame, text="标记完成", command=self.toggle_task_status).pack(side="left", padx=5)
        ttk.Button(button_frame, text="删除任务", command=self.delete_task).pack(side="left", padx=5)
        ttk.Button(button_frame, text="删除已完成", command=self.delete_completed).pack(side="left", padx=5)
        ttk.Button(button_frame, text="保存列表", command=self.save_tasks).pack(side="right", padx=5)
        ttk.Button(button_frame, text="加载列表", command=self.load_tasks).pack(side="right", padx=5)
        
        # 状态栏
        self.status_var = tk.StringVar()
        self.status_bar = ttk.Label(self.root, textvariable=self.status_var, relief="sunken", anchor="w")
        self.status_bar.pack(fill="x", padx=20, pady=(0, 10))
        self.update_status()
    
    def _auto_save(self):
        """自动保存任务到output.json"""
        try:
            with open("output.json", "w") as f:
                json.dump(self.tasks, f, indent=2)
        except Exception as e:
            messagebox.showerror("自动保存错误", f"自动保存失败:\n{str(e)}")

    def add_task(self):
        task_text = self.task_entry.get().strip()
        if not task_text:
            messagebox.showwarning("输入错误", "请输入任务描述")
            return
            
        # 生成唯一ID - 使用当前最大ID+1
        new_id = max([task["id"] for task in self.tasks], default=0) + 1
        task = {
            "id": new_id,  # 使用新生成的ID
            "text": task_text,
            "completed": False,
            "date": datetime.now().strftime("%Y-%m-%d %H:%M")
        }
        self.tasks.insert(0, task)
        
        self.update_task_list()
        self.task_entry.delete(0, tk.END)
        self.update_status()
        self._auto_save()
        # 新增以下代码，自动选中新添加的任务
        self.tree.selection_set(str(new_id))

    def update_task_list(self):
        # 清空当前列表
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 添加任务到列表（确保iid严格等于任务ID的字符串）
        for task in self.tasks:
            status = "已完成" if task["completed"] else "待处理"
            tags = ("completed",) if task["completed"] else ()
            # 关键验证：确保iid与任务ID完全一致
            self.tree.insert(
                "", "end", 
                iid=str(task["id"]),  # 必须使用任务ID的字符串形式
                text=str(task["id"]), 
                values=(task["text"], status, task["date"]), 
                tags=tags
            )
        
        # 设置完成任务的样式
        self.tree.tag_configure("completed", foreground="#888888", font=("Arial", 10, "overstrike"))
    
    def toggle_task_status(self, event=None):
        selected = self.tree.selection()
        if not selected:
            messagebox.showinfo("提示", "请先选择一个任务")
            return
            
        task_id = int(selected[0])
        for task in self.tasks:
            if task["id"] == task_id:
                task["completed"] = not task["completed"]
                break
                
        self.update_task_list()
        self.update_status()
        self._auto_save()  # 添加自动保存

    def delete_task(self, item_id=None):
        # 确保selected始终是元组类型（兼容右键菜单和按钮调用）
        selected = (item_id,) if item_id is not None else self.tree.selection()
        if not selected:
            messagebox.showinfo("提示", "请先选择一个任务")
            return
            
        task_id = int(selected[0])  # 现在selected一定是元组，可安全取[0]
        self.tasks = [task for task in self.tasks if task["id"] != task_id]
        self.update_task_list()
        self.update_status()
        self._auto_save()

    def edit_task_content(self, event=None, item_id=None):
        """编辑任务内容"""
        selected = item_id if item_id is not None else (self.tree.selection()[0] if self.tree.selection() else None)
        if not selected:
            return
            
        task_id = int(selected)
        task = next((t for t in self.tasks if t["id"] == task_id), None)
        if not task:
            return
            
        # 创建编辑窗口
        edit_win = tk.Toplevel(self.root)
        edit_win.title("编辑任务内容")
        
        tk.Label(edit_win, text="任务内容:").pack(padx=10, pady=5)
        content_entry = tk.Entry(edit_win, width=40)
        content_entry.insert(0, task["text"])
        content_entry.pack(padx=10, pady=5)
        content_entry.focus()
        
        def save_edit():
            new_text = content_entry.get().strip()
            if new_text:
                task["text"] = new_text
                self.update_task_list()
                self._auto_save()
                edit_win.destroy()
        
        tk.Button(edit_win, text="保存", command=save_edit).pack(pady=10)
        edit_win.bind("<Return>", lambda e: save_edit())

    def show_context_menu(self, event):
        """显示右键菜单（优化：自动选中点击的行）"""
        item = self.tree.identify_row(event.y)
        if item:
            self.tree.selection_set(item)  # 新增：自动选中点击的行
            menu = tk.Menu(self.root, tearoff=0)
            menu.add_command(label="编辑内容", command=lambda: self.edit_task_content(None, item))
            menu.add_command(label="删除任务", command=lambda: self.delete_task(item))
            menu.post(event.x_root, event.y_root)

    def delete_completed(self):
        if not any(task["completed"] for task in self.tasks):
            messagebox.showinfo("提示", "没有已完成的任务")
            return
            
        self.tasks = [task for task in self.tasks if not task["completed"]]
        self.update_task_list()
        self.update_status()
        self._auto_save()  # 添加自动保存
    
    def save_tasks(self):
        if not self.tasks:
            messagebox.showinfo("提示", "没有任务可保存")
            return
            
        file_path = filedialog.asksaveasfilename(
            defaultextension=".json",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
        )
        
        if not file_path:
            return
            
        try:
            with open(file_path, "w") as f:
                json.dump(self.tasks, f, indent=2)
            messagebox.showinfo("成功", f"任务列表已保存到:\n{file_path}")
        except Exception as e:
            messagebox.showerror("错误", f"保存文件时出错:\n{str(e)}")
    
    def _load_tasks_data(self, tasks_data):
        """内部方法：加载任务数据并更新界面"""
        self.tasks = tasks_data
        self.update_task_list()
        self.update_status()
        return True

    def load_tasks(self):
        file_path = filedialog.askopenfilename(
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
        )
        
        if not file_path:
            return
            
        try:
            with open(file_path, "r") as f:
                tasks_data = json.load(f)
            if self._load_tasks_data(tasks_data):
                messagebox.showinfo("成功", f"已从文件加载任务列表:\n{file_path}")
        except Exception as e:
            messagebox.showerror("错误", f"加载文件时出错:\n{str(e)}")
    
    def load_history_data(self):
        sample_tasks = [
            {"id": 1, "text": "完成TodoList应用开发", "completed": True, "date": "2023-10-15 09:30"},
            {"id": 2, "text": "学习Python高级特性", "completed": False, "date": "2023-10-16 10:15"},
            {"id": 3, "text": "准备项目演示文稿", "completed": False, "date": "2023-10-16 14:20"},
            {"id": 4, "text": "回复重要邮件", "completed": False, "date": "2023-10-17 08:45"},
            {"id": 5, "text": "团队周会", "completed": True, "date": "2023-10-17 13:00"},
        ]
        try:
            with open("output.json", "r") as f:
                self._load_tasks_data(json.load(f))
        except Exception as e:
            messagebox.showerror("错误", f"加载默认数据时出错:\n{str(e)}")
            # 如果加载失败，使用空列表
            self.tasks = []
    
    def on_closing(self):
        # if messagebox.askyesno("退出", "确定要退出程序吗？"):
        self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = TodoListApp(root)
    root.mainloop()